package cn.admin.config.common.protocol;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public abstract class ProtocolPacket implements
        ProtocolElement,Iterable<ProtocolElement> {

    private transient List<ProtocolElement> elements = new ArrayList<>();

    protected void addElement(ProtocolElement element) {

        if (element == null) {
            new Exception("Add null element").printStackTrace();
        }
        this.elements.add(element);

    }

    protected boolean setElement(ProtocolElement element) {

        for (int i = 0;i < this.elements.size();i ++) {
            if (this.elements.get(i).uid().equals(element.uid())) {
                this.elements.set(i,element);
                return false;
            }
        }
        this.elements.add(element);
        return true;
    }

    protected boolean removeElement(ProtocolElement element) {
        for(int index = 0; index < this.elements.size(); ++index) {
            if (this.elements.get(index) == element) {
                this.elements.remove(index);
                return true;
            }
        }

        return false;
    }

    protected ProtocolElement getElement(ProtocolElementUid uid) {

        for (ProtocolElement element : elements) {
            if (element.uid().equals(uid)) {
                return element;
            }
        }
        return null;
    }

    protected List<ProtocolElement> getAll() {
        return this.elements;
    }

    protected void reset() {
        this.elements.clear();
    }

    public int countElements() {
        return this.elements.size();
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        int count = in.readInt();
        this.elements = new ArrayList<>();

        for (int i = 0;i < count;i ++) {
            int uid = in.readInt();
            ProtocolElement element;
            try {
                Object object = in.readObject();
                element = (ProtocolElement) object;
                if (uid != element.uid().toInt()) {
                    element = new InvalidElement(uid,
                            new ProtocolElementUidUnmatchedException(element,uid));
                }
            } catch (Exception e) {
                element = new InvalidElement(uid,e);
            }
            this.elements.add(element);
        }
    }

    private void writeObject(ObjectOutputStream out) throws IOException {

        out.writeInt(this.elements.size());
        for (ProtocolElement element : elements) {
            out.writeInt(element.uid().toInt());
            out.writeObject(element);
        }

    }

    @Override
    public Iterator<ProtocolElement> iterator() {
        return this.elements.iterator();
    }
}
